﻿using System;
using System.IO;
using System.Threading.Tasks;
using Looptribe.Moodlin8.Model;
using Looptribe.Moodlin8.Model.Api;
using Looptribe.Moodlin8.UIHelper;
using Looptribe.Moodlin8.View;
using Looptribe.Moodlin8.ViewModel;
using Looptribe.WinRT.Toolkit;
using Microsoft.Practices.ServiceLocation;
using Windows.ApplicationModel.Resources;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Popups;

namespace Looptribe.Moodlin8.Controller
{
    public class ApplicationController
    {
        private const string CredentialsSettingsContainer = "Credentials";

        protected INavigationService NavigationService { get { return ServiceLocator.Current.GetInstance<INavigationService>(); } }

        protected ApplicationDataContainer LocalSettings { get { return ApplicationData.Current.LocalSettings; } }

        private User _currentUser;
        public User CurrentUser { get { return _currentUser; } }

        private WebserviceInfo _webserviceInfo;
        public WebserviceInfo Info { get { return _webserviceInfo; } }

        private readonly ResourceLoader _resourceLoader = new ResourceLoader();

        protected IMoodleApiService Api
        { get { return ServiceLocator.Current.GetInstance<IMoodleApiService>(); } }

        public async Task<string> GetApiTokenAsync(ServiceCredentials credentials)
        {
            var response = await Api.AuthenticateAsync(credentials);

            //TODO: check
            if (response.Status != Status.Ok)
                return null;

            if (string.IsNullOrEmpty(response.Data))
                return null;

            await GetCurrentUserAsync();

            return response.Data;
        }

        public async Task<bool> LoginAsync()
        {
            if (Api.IsLogged)
                return true;
            var credentials = new ServiceCredentials { ServiceName = ServiceCredentials.Moodlin8ServiceName };
            LoadCredentials(credentials);
            if (ServiceCredentials.IsNullOrEmpty(credentials))
                return false;
            await GetApiTokenAsync(credentials);
            return Api.IsLogged;
        }

        public void Logout()
        {
            if (Api.IsLogged)
            {
                RemoveCredentials();
                Api.Logout();
                NavigationService.Navigate<LoginPage>();
                NavigationService.ClearHistory();
            }
        }

        public void GotoHub()
        {
            NavigationService.Navigate<HubPage>();
        }

        public void GotoCourses()
        {
            NavigationService.Navigate<CoursesPage>();
        }

        public void GotoCourse(Course course)
        {
            NavigationService.Navigate<CoursePage>(course);
        }

        public void GotoCourseContent(CourseContent content)
        {
            NavigationService.Navigate<CourseContentPage>(content);
        }

        public void GotoCourseUsers(Course course)
        {
            NavigationService.Navigate<CourseUsersPage>(course);
        }

        public void GotoNextAssignments(Course course)
        {
            NavigationService.Navigate<NextAssignmentPage>(course);
        }

        public void GotoCorrectedAssignments(Course course)
        {
            NavigationService.Navigate<CorrectedAssignmentPage>(course);
        }

        public void GotoAssignment(AssignmentWrapper assignment)
        {
            NavigationService.Navigate<AssignmentPage>(assignment);
        }

        public void GotoUploads()
        {
            NavigationService.Navigate<UploadsPage>();
        }

        public void GotoTeacher(CourseUser user)
        {
            NavigationService.Navigate<TeacherPage>(user);
        }

        public void GotoUserMessages(User user)
        {
            NavigationService.Navigate<UserMessagesPage>(user);
        }

        public void GotoCourseEvents(Course course)
        {
            NavigationService.Navigate<CourseEventsPage>(course);
        }

        public void GotoDate(DateTime date)
        {
            NavigationService.Navigate<DayEventsPage>(date);
        }

        public async Task OpenUriAsync(Uri uri)
        {
            await Windows.System.Launcher.LaunchUriAsync(uri);
        }

        public async Task<bool> OpenFileAsync(IStorageFile file)
        {
            return await Windows.System.Launcher.LaunchFileAsync(file);
        }

        public async Task<bool> OpenModuleContentAsync(ModuleContent moduleContent)
        {
            if (moduleContent.Type.Equals(ModuleContent.TypeFile))
            {
                var local = await Api.DownloadFileAsync(Api.GetDownloadUrl(moduleContent));
                if (local.Status != Status.Ok)
                    return false;
                await OpenFileAsync(local.Data);
            }
            else
                await OpenUriAsync(new Uri(Api.GetDownloadUrl(moduleContent)));
            return true;
        }

        public async Task<bool> OpenFileAsync(File file)
        {
            var response = await Api.DownloadFileAsync(file);
            if (response.Status != Status.Ok || response.Data == null)
                return false;
            return await OpenFileAsync(response.Data);
        }

        private async Task<User> GetCurrentUserAsync()
        {
            var response = await Api.GetWebserviceInfo();
            _webserviceInfo = response.Data;

            var user = new User
                           {
                               Id = _webserviceInfo.Userid,
                               Username = _webserviceInfo.Username,
                               Firstname = _webserviceInfo.Firstname,
                               Lastname = _webserviceInfo.Lastname,
                               Fullname = _webserviceInfo.Fullname,
                               ProfileImageUrl = _webserviceInfo.UserPictureUrl
                           };

            _currentUser = user;

            return user;
        }

        public void StoreCredentials(ServiceCredentials credentials)
        {
            var container = LocalSettings.CreateContainer(CredentialsSettingsContainer, ApplicationDataCreateDisposition.Always);
            container.Values["Username"] = credentials.Username;
            container.Values["Password"] = credentials.Password;
            container.Values["BaseUri"] = credentials.BaseUri.ToString();
            container.Values["ServiceName"] = credentials.ServiceName;
        }

        public void LoadCredentials(ServiceCredentials credentials)
        {
            if (!LocalSettings.Containers.ContainsKey(CredentialsSettingsContainer))
                return;
            var container = LocalSettings.CreateContainer(CredentialsSettingsContainer, ApplicationDataCreateDisposition.Existing);
            if (container == null)
                return;
            if (container.Values.ContainsKey("Username"))
                credentials.Username = container.Values["Username"] as string;
            if (container.Values.ContainsKey("Password"))
                credentials.Password = container.Values["Password"] as string;
            if (container.Values.ContainsKey("BaseUri"))
                credentials.BaseUri = new Uri(container.Values["BaseUri"].ToString());
            if (container.Values.ContainsKey("ServiceName"))
                credentials.ServiceName = container.Values["ServiceName"] as string;
        }

        public void RemoveCredentials()
        {
            if (LocalSettings.Containers.ContainsKey(CredentialsSettingsContainer))
                LocalSettings.DeleteContainer(CredentialsSettingsContainer);
        }

        public async Task ShowMessageDialogAsync(string content)
        {
            var dialog = new MessageDialog(content);
            await dialog.ShowAsync();
        }

        public async Task<IStorageFile> PickFileAsync(string filter)
        {
            var openPicker = new FileOpenPicker
            {
                ViewMode = PickerViewMode.List,
                SuggestedStartLocation = PickerLocationId.DocumentsLibrary
            };
            openPicker.FileTypeFilter.Add(filter);

            return await openPicker.PickSingleFileAsync();
        }

        public bool IsCoursePinned(Course course)
        {
            return SecondaryTileManager.CourseExists(course.Id);
        }

        public async Task<bool> PinCourseAsync(Course course, Rect rect)
        {
            return await SecondaryTileManager.PinCourse(course, rect);
        }

        public async Task<bool> UnpinCourseAsync(Course course, Rect rect)
        {
            return await SecondaryTileManager.UnpinCourse(course.Id, rect);
        }

        public string GetResourceString(string resource)
        {
            return _resourceLoader.GetString(resource);
        }
    }

}
